home *** CD-ROM | disk | FTP | other *** search
/ Just Call Me Internet / Just Call Me Internet.iso / prog / atari / c / nos042_s / zm.c < prev    next >
C/C++ Source or Header  |  1994-09-16  |  24KB  |  1,063 lines

  1. /****************************************************************************
  2. *    Language     :    Turbo C 2.0                                                *
  3. *    Logfile        :    zm.c                                                    *
  4. *    Project        :    Comms Library.                                            *
  5. *    Date         :    25 Jan 90                                                *
  6. *    Revision     :    1.1        GT    PC version.                                    *
  7. *    25 Oct 92    :    1.2        GT    KA9Q mods.                                    *
  8. *****************************************************************************
  9. *    Purpose        :    ZMODEM protocol primitives.                                *
  10. *****************************************************************************
  11. *                :    This module is based on the equivalent module in the    *
  12. *                :    31 Aug 87 version of rz/sz.                                *
  13. *    $Id: zm.c 1.1 93/01/16 18:38:59 ROOT_DOS Exp $
  14. ****************************************************************************/
  15.  
  16. /*
  17.  *   Z M . C
  18.  *    ZMODEM protocol primitives
  19.  *    07-28-87  Chuck Forsberg Omen Technology Inc
  20.  *
  21.  * Entry point Functions:
  22.  *    _zsbhdr (type, hdr) send binary header
  23.  *    _zshhdr (type, hdr) send hex header
  24.  *    _zgethdr (hdr, eflag) receive header - binary or hex
  25.  *    _zsdata (buf, len, frameend) send data
  26.  *    _zrdata (buf, len) receive data
  27.  *    _stohdr (pos) store position data in _Txhdr
  28.  *    long _rclhdr (hdr) recover position offset from header
  29.  */
  30.  
  31. #ifndef CANFDX
  32. #include    "zmodem.h"
  33.  
  34. int _Rxtimeout = 100;        /* Tenths of seconds to wait for something */
  35. #endif
  36.  
  37. #include    <setjmp.h>
  38. #include "config.h"
  39. #include    "sz.h"
  40. #include    "zm.h"
  41. #include    "rbsb.h"
  42.  
  43.  
  44. #ifndef UNSL
  45. #define UNSL    unsigned
  46. #endif
  47.  
  48.  
  49. /****************************************************************************
  50. *    Local prototypes.                                                        *
  51. ****************************************************************************/
  52.  
  53. static int noxrd7 (void);
  54. static int zdlread (void);
  55. static int zgeth1 (void);
  56. static int zgethex (void);
  57. static void zputhex (int c);
  58. static int zrbhdr (char *hdr);
  59. static int zrbhdr32 (char *hdr);
  60. static int zrdat32 (char *buf, int length);
  61. static int zrhhdr (char *hdr);
  62. static void zsbh32 (char *hdr, int type);
  63. static void zsda32 (char *buf, int length, int frameend);
  64. static void zsendline (int c);
  65.  
  66.  
  67. /****************************************************************************
  68. *    Globals used by ZMODEM functions.                                        *
  69. ****************************************************************************/
  70.  
  71. static int Rxframeind;        /* ZBIN ZBIN32, or ZHEX type of frame received    */
  72. static int Rxtype;            /* Type of header received                         */
  73. int _Rxcount;                /* Count of data bytes received                 */
  74. char _Rxhdr[4];                /* Received header                                 */
  75. char _Txhdr[4];                /* Transmitted header                             */
  76. long _Rxpos;                /* Received file position                         */
  77. long _Txpos;                /* Transmitted file position                     */
  78. int _Txfcs32;                /* TRUE - send binary frames with 32 bit FCS     */
  79. int _Crc32t;                /* Display flag - 32 bit CRC being sent         */
  80. int _Crc32;                    /* Display flag - 32 bit CRC being received        */
  81. int _Znulls;                    /* No of nulls to send at start of ZDATA hdr    */
  82. char _Attn[ZATTNLEN + 1];    /* Attention string rx sends to tx on err        */
  83.  
  84.  
  85. static char *frametypes[] =
  86.     {
  87.     "Carrier Lost",            /* -3 */
  88.     "TIMEOUT",                /* -2 */
  89.     "ERROR",                /* -1 */
  90. #define FTOFFSET     3
  91.     "ZRQINIT",
  92.     "ZRINIT",
  93.     "ZSINIT",
  94.     "ZACK",
  95.     "ZFILE",
  96.     "ZSKIP",
  97.     "ZNAK",
  98.     "ZABORT",
  99.     "ZFIN",
  100.     "ZRPOS",
  101.     "ZDATA",
  102.     "ZEOF",
  103.     "ZFERR",
  104.     "ZCRC",
  105.     "ZCHALLENGE",
  106.     "ZCOMPL",
  107.     "ZCAN",
  108.     "ZFREECNT",
  109.     "ZCOMMAND",
  110.     "ZSTDERR",
  111.     "xxxxx"
  112. #define FRTYPES 22            /* Total number of frame types in this array    */
  113.                             /*  not including psuedo negative entries        */
  114.     };
  115.  
  116.  
  117. /****************************************************************************
  118. *    _zsbhdr                                                                    *
  119. *    Send ZMODEM binary header <hdr> of type <type>.                            *
  120. ****************************************************************************/
  121.  
  122. void _zsbhdr (int type, char *hdr)
  123.     {
  124.     int n;
  125.     unsigned short crc;
  126.  
  127.     _vfile ("_zsbhdr: %s %lx", frametypes[type + FTOFFSET], _rclhdr (hdr));
  128.     if (type == ZDATA)
  129.         for (n = _Znulls; --n >= 0;)
  130.             zsendline (0);
  131.  
  132.     _xsendline (ZPAD);
  133.     _xsendline (ZDLE);
  134.  
  135.     if ((_Crc32t = _Txfcs32) != 0)
  136.         zsbh32 (hdr, type);
  137.     else
  138.         {
  139.         _xsendline (ZBIN);
  140.         zsendline (type);
  141.         crc = updcrc (type, 0);
  142.  
  143.         for (n = 4; --n >= 0; ++hdr)
  144.             {
  145.             zsendline (*hdr);
  146.             crc = updcrc ((0377 & *hdr), crc);
  147.             }
  148.             
  149.         crc = updcrc (0, updcrc (0, crc));
  150.         zsendline (crc >> 8);
  151.         zsendline (crc);
  152.         }
  153.  
  154.     if (type != ZDATA)
  155.         _flushmo ();
  156.  
  157.     }    /* void _zsbhdr (int type, char *hdr) */
  158.     
  159.  
  160. /****************************************************************************
  161. *    zsbh32                                                                    *
  162. *    Send ZMODEM binary header <hdr> of type <type>.                            *
  163. ****************************************************************************/
  164.  
  165. static void zsbh32 (char *hdr, int type)
  166.     {
  167.     int n;
  168.     UNSL long crc;
  169.  
  170.     _xsendline (ZBIN32);
  171.     zsendline (type);
  172.     crc = 0xFFFFFFFFL;
  173. #ifdef    DEBUGZ
  174.     _vfile ("\n%s:%d zsbh32 initial CRC = %08lx", __FILE__, __LINE__, crc);
  175. #endif
  176.     crc = UPDC32 (type, crc);
  177. #ifdef    DEBUGZ
  178.     _vfile ("%s:%d zsbh32 byte = %x, CRC = %08lx", __FILE__, __LINE__,
  179.            type, crc);
  180. #endif
  181.  
  182.     for (n = 4; --n >= 0; ++hdr)
  183.         {
  184.         crc = UPDC32 ((0377 & *hdr), crc);
  185. #ifdef    DEBUGZ
  186.         _vfile ("%s:%d zsbh32 byte = %x, CRC = %08lx", __FILE__, __LINE__,
  187.                (0377 & *hdr), crc);
  188. #endif
  189.         zsendline (*hdr);
  190.         }
  191.         
  192.     crc = ~crc;
  193. #ifdef    DEBUGZ
  194.     _vfile ("%s:%d zsbh32 sent CRC = %08lx", __FILE__, __LINE__, crc);
  195. #endif
  196.     for (n = 4; --n >= 0;)
  197.         {
  198.         zsendline ((int) crc);
  199.         crc >>= 8;
  200.         }
  201.         
  202.     }    /* static void zsbh32 (char *hdr, int type) */
  203.     
  204.  
  205. /****************************************************************************
  206. *    _zshhdr                                                                    *
  207. *    Send ZMODEM HEX header <hdr> of type <type>.                            *
  208. ****************************************************************************/
  209.  
  210. void _zshhdr (int type, char *hdr)
  211.     {
  212.     int n;
  213.     unsigned short crc;
  214.  
  215.     _vfile ("_zshhdr: %s %lx", frametypes[type + FTOFFSET], _rclhdr (hdr));
  216.     _sendline (ZPAD);
  217.     _sendline (ZPAD);
  218.     _sendline (ZDLE);
  219.     _sendline (ZHEX);
  220.     zputhex (type);
  221.     _Crc32t = 0;
  222.  
  223.     crc = updcrc (type, 0);
  224.     for (n = 4; --n >= 0; ++hdr)
  225.         {
  226.         zputhex (*hdr);
  227.         crc = updcrc ((0377 & *hdr), crc);
  228.         }
  229.  
  230.     crc = updcrc (0, updcrc (0, crc));
  231.     zputhex (crc >> 8);
  232.     zputhex (crc);
  233.  
  234.     /* Make it printable on remote machine */
  235.  
  236.     _sendline (015);
  237.     _sendline (012);
  238.  
  239.     /* Uncork the remote in case a fake XOFF has stopped data flow. */
  240.     
  241.     if (type != ZFIN && type != ZACK)
  242.         _sendline (021);
  243.  
  244.     _flushmo ();
  245.     }    /* void _zshhdr (int type, char *hdr) */
  246.     
  247.  
  248. /****************************************************************************
  249. *    _zsdata                                                                    *
  250. *    Send binary array <buf> of length <length>, with ending ZDLE sequence     *
  251. *    <frameend>.                                                                *
  252. ****************************************************************************/
  253.  
  254. void _zsdata (char *buf, int length, int frameend)
  255.     {
  256.     unsigned short crc;
  257.  
  258.     _vfile ("_zsdata: length=%d end=%x", length, frameend);
  259.     if (_Crc32t)
  260.         zsda32 (buf, length, frameend);
  261.     else
  262.         {
  263.         crc = 0;
  264.         for (;--length >= 0; ++buf)
  265.             {
  266.             zsendline (*buf);
  267.             crc = updcrc ((0377 & *buf), crc);
  268.             }
  269.  
  270.         _xsendline (ZDLE);
  271.         _xsendline (frameend);
  272.         crc = updcrc (frameend, crc);
  273.  
  274.         crc = updcrc (0, updcrc (0, crc));
  275.         zsendline (crc >> 8);
  276.         zsendline (crc);
  277.         }
  278.  
  279.     if (frameend == ZCRCW)
  280.         {
  281.         _xsendline (XON);
  282.         _flushmo ();
  283.         }
  284.         
  285.     }    /* void _zsdata (char *buf, int length, int frameend) */
  286.     
  287.  
  288. /****************************************************************************
  289. *    zsda32                                                                    *
  290. *    Send <length> bytes from <buf> followed by ZDLE <frameend> with a 32    *
  291. *    bit CRC.                                                                *
  292. ****************************************************************************/
  293.  
  294. static void zsda32 (char *buf, int length, int frameend)
  295.     {
  296.     UNSL long crc;
  297.  
  298.     crc = 0xFFFFFFFFL;
  299. #ifdef    DEBUGZ
  300.     _vfile ("\n%s:%d zsda32 initial CRC = %08lx", __FILE__, __LINE__, crc);
  301. #endif
  302.     for (;--length >= 0; ++buf)
  303.         {
  304.         crc = UPDC32 ((0377 & *buf), crc);
  305. #if    0
  306.         _vfile ("%s:%d zsda32 byte = %x, CRC = %08lx", __FILE__, __LINE__,
  307.                (0377 & *buf), crc);
  308. #endif
  309.         zsendline (*buf);
  310.         }
  311.  
  312.     _xsendline (ZDLE);
  313.     _xsendline (frameend);
  314.     crc = UPDC32 (frameend, crc);
  315. #ifdef    DEBUGZ
  316.     _vfile ("%s:%d zsda32 byte = %x, CRC = %08lx", __FILE__, __LINE__,
  317.            frameend, crc);
  318. #endif
  319.  
  320.     crc = ~crc;
  321. #ifdef    DEBUGZ
  322.     _vfile ("%s:%d zsda32 sent CRC = %08lx", __FILE__, __LINE__, crc);
  323. #endif
  324.     for (length = 4; --length >= 0;)
  325.         {
  326.         zsendline ((int) crc);
  327.         crc >>= 8;
  328.         }
  329.  
  330.     }    /* static void zsda32 (char *buf, int length, int frameend) */
  331.     
  332.  
  333. /****************************************************************************
  334. *    _zrdata                                                                    *
  335. *    Receive array <buf> of max <length> with ending ZDLE sequence and CRC.    *
  336. *    Returns the ending character or error code.  NB: On errors may store     *
  337. *    <length> + 1 bytes!                                                        *
  338. ****************************************************************************/
  339.  
  340. int _zrdata (char *buf, int length)
  341.     {
  342.     int c;
  343.     unsigned short crc;
  344.     char *end;
  345.     int d;
  346.  
  347.     if (Rxframeind == ZBIN32)
  348.         return zrdat32 (buf, length);
  349.  
  350.     crc = _Rxcount = 0;
  351.     end = buf + length;
  352.     while (buf <= end)
  353.         {
  354.         if ((c = zdlread ()) & ~0377)
  355.             {
  356. crcfoo:
  357.            switch (c)
  358.                 {
  359.                 case GOTCRCE:
  360.                 case GOTCRCG:
  361.                 case GOTCRCQ:
  362.                 case GOTCRCW:
  363.                     crc = updcrc (((d = c) & 0377), crc);
  364.                     if ((c = zdlread ()) & ~0377)
  365.                         goto crcfoo;
  366.  
  367.                     crc = updcrc (c, crc);
  368.                     if ((c = zdlread ()) & ~0377)
  369.                         goto crcfoo;
  370.  
  371.                     crc = updcrc (c, crc);
  372.                     if (crc & 0xFFFF)
  373.                         {
  374.                         _zperr_ ("Bad data CRC");
  375.                         return ERROR;
  376.                         }
  377.  
  378.                     _Rxcount = (int) (length - (end - buf));
  379.                     _vfile ("_zrdata: cnt = %d ret = %x", _Rxcount, d);
  380.                     return d;
  381.  
  382.                 case GOTCAN:
  383.                     _zperr_ ("Sender cancelled");
  384.                     return ZCAN;
  385.  
  386.                 case ZTIMEOUT:
  387.                     _zperr_ ("TIMEOUT");
  388.                     return c;
  389.  
  390.                 default:
  391.                     _zperr_ ("Bad data subpacket");
  392.                     return c;
  393.                 }    /* switch (c) */
  394.                 
  395.             }    /* if ((c = zdlread ()) & ~0377) */
  396.             
  397.         *buf++ = (char) c;
  398.         crc = updcrc (c, crc);
  399.         }    /* while (buf <= end) */
  400.         
  401.     _zperr_ ("Data subpacket too long");
  402.     return ERROR;
  403.     }    /* int _zrdata (char *buf, int length) */
  404.     
  405.  
  406. /****************************************************************************
  407. *    zrdat32                                                                    *
  408. *    As _zrdata with 32 bit CRC.                                                *
  409. ****************************************************************************/
  410.  
  411. static int zrdat32 (char *buf, int length)
  412.     {
  413.     int c;
  414.     UNSL long crc;
  415.     char *end;
  416.     int d;
  417.  
  418.     crc = 0xFFFFFFFFL;
  419.     _Rxcount = 0;
  420.     end = buf + length;
  421.     while (buf <= end)
  422.         {
  423.         if ((c = zdlread ()) & ~0377)
  424.             {
  425. crcfoo:
  426.            switch (c)
  427.                 {
  428.                 case GOTCRCE:
  429.                 case GOTCRCG:
  430.                 case GOTCRCQ:
  431.                 case GOTCRCW:
  432.                     d = c;
  433.                     c &= 0377;
  434.                     crc = UPDC32 (c, crc);
  435.                     if ((c = zdlread ()) & ~0377)
  436.                         goto crcfoo;
  437.  
  438.                     crc = UPDC32 (c, crc);
  439.                     if ((c = zdlread ()) & ~0377)
  440.                         goto crcfoo;
  441.  
  442.                     crc = UPDC32 (c, crc);
  443.                     if ((c = zdlread ()) & ~0377)
  444.                         goto crcfoo;
  445.  
  446.                     crc = UPDC32 (c, crc);
  447.                     if ((c = zdlread ()) & ~0377)
  448.                         goto crcfoo;
  449.  
  450.                     crc = UPDC32 (c, crc);
  451.                     if (crc != 0xDEBB20E3L)
  452.                         {
  453.                         _zperr_ ("Bad data CRC");
  454.                         return ERROR;
  455.                         }
  456.  
  457.                     _Rxcount = (int) (length - (end - buf));
  458.                     _vfile ("zrdat32: cnt = %d ret = %x", _Rxcount, d);
  459.                     return d;
  460.  
  461.                 case GOTCAN:
  462.                     _zperr_ ("Sender cancelled");
  463.                     return ZCAN;
  464.  
  465.                 case ZTIMEOUT:
  466.                     _zperr_ ("TIMEOUT");
  467.                     return c;
  468.  
  469.                 default:
  470.                     _zperr_ ("Bad data subpacket");
  471.                     return c;
  472.                 }    /* switch (c) */
  473.                 
  474.             }    /* if ((c = zdlread ()) & ~0377) */
  475.             
  476.         *buf++ = (char) c;
  477.         crc = UPDC32 (c, crc);
  478.         }    /* while (buf <= end) */
  479.         
  480.     _zperr_ ("Data subpacket too long");
  481.     return ERROR;
  482.     }    /* static int zrdat32 (char *buf, int length) */
  483.     
  484.  
  485. /****************************************************************************
  486. *    _zgethdr                                                                    *
  487. *    Read a ZMODEM header to <hdr>, either binary or hex.  <eflag> controls    *
  488. *    local display of non zmodem characters:                                    *
  489. *    0:  no display                                                            *
  490. *    1:  display printing characters only                                    *
  491. *    2:  display all non ZMODEM characters                                    *
  492. *     On success, set Zmodem to 1, set _Rxpos and return type of header.        *
  493. *    Otherwise return negative on error.                                        *
  494. *    Return ERROR instantly if ZCRCW sequence, for fast error recovery.        *
  495. ****************************************************************************/
  496.  
  497. int _zgethdr (char *hdr, int eflag)
  498.     {
  499.     int c, n, cancount;
  500.  
  501.     n = _Zrwindow + _Baud_z;            /* Max bytes before start of frame    */
  502.     Rxframeind = Rxtype = 0;
  503.  
  504. startover:
  505.     cancount = 5;
  506.     
  507. again:
  508.     /* Return immediate ERROR if ZCRCW sequence seen */
  509.     
  510.     switch (c = _readline (_Rxtimeout))
  511.         {
  512.         case RCDO:
  513.         case ZTIMEOUT:
  514.             goto fifi;
  515.  
  516.         case CAN:
  517. gotcan:
  518.            if (--cancount <= 0)
  519.                 {
  520.                 c = ZCAN;
  521.                 goto fifi;
  522.                 }
  523.  
  524.             switch (c = _readline (1))
  525.                 {
  526.                 case ZTIMEOUT:
  527.                     goto again;
  528.  
  529.                 case ZCRCW:
  530.                     c = ERROR;
  531.  
  532.                     /* **** FALL THRU TO **** */
  533.  
  534.                 case RCDO:
  535.                     goto fifi;
  536.  
  537.                 default:
  538.                     break;
  539.  
  540.                 case CAN:
  541.                     if (--cancount <= 0)
  542.                         {
  543.                         c = ZCAN;
  544.                         goto fifi;
  545.                         }
  546.  
  547.                     goto again;
  548.                 }    /* switch (c = _readline (1)) */
  549.                 
  550.         /* **** FALL THRU TO **** */
  551.  
  552.         default:
  553. agn2:
  554.            if (--n == 0)
  555.                 {
  556.                 _zperr_ ("Garbage count exceeded");
  557.                 return (ERROR);
  558.                 }
  559.  
  560.             if (eflag && ((c &= 0177) & 0140))
  561.                 _bttyout (c);
  562.             else if (eflag > 1)
  563.                 _bttyout (c);
  564.  
  565.             goto startover;
  566.  
  567.         case ZPAD | 0200:                /* This is what we want.            */
  568.         case ZPAD:                        /* This is what we want.            */
  569.             break;
  570.         }    /* switch (c = _readline (_Rxtimeout)) */
  571.         
  572.     cancount = 5;
  573.  
  574. splat:
  575.     switch (c = noxrd7 ())
  576.         {
  577.         case ZPAD:
  578.             goto splat;
  579.  
  580.         case RCDO:
  581.         case ZTIMEOUT:
  582.             goto fifi;
  583.  
  584.         default:
  585.             goto agn2;
  586.  
  587.         case ZDLE:                        /* This is what we want.             */
  588.             break;
  589.         }    /* switch (c = noxrd7 ()) */
  590.  
  591.     switch (c = noxrd7 ())
  592.         {
  593.         case RCDO:
  594.         case ZTIMEOUT:
  595.             goto fifi;
  596.  
  597.         case ZBIN:
  598.             Rxframeind = ZBIN;
  599.             _Crc32 = FALSE;
  600.             c = zrbhdr (hdr);
  601.             break;
  602.  
  603.         case ZBIN32:
  604.             _Crc32 = Rxframeind = ZBIN32;
  605.             c = zrbhdr32 (hdr);
  606.             break;
  607.  
  608.         case ZHEX:
  609.             Rxframeind = ZHEX;
  610.             _Crc32 = FALSE;
  611.             c = zrhhdr (hdr);
  612.             break;
  613.  
  614.         case CAN:
  615.             goto gotcan;
  616.  
  617.         default:
  618.             goto agn2;
  619.         }    /* switch (c = noxrd7 ()) */
  620.         
  621.     _Rxpos = hdr[ZP3] & 0377;
  622.     _Rxpos = (_Rxpos << 8) + (hdr[ZP2] & 0377);
  623.     _Rxpos = (_Rxpos << 8) + (hdr[ZP1] & 0377);
  624.     _Rxpos = (_Rxpos << 8) + (hdr[ZP0] & 0377);
  625.  
  626. fifi:
  627.     switch (c)
  628.         {
  629.         case GOTCAN:
  630.             c = ZCAN;
  631.  
  632.             /* **** FALL THRU TO **** */
  633.  
  634.         case ZNAK:
  635.         case ZCAN:
  636.         case ERROR:
  637.         case ZTIMEOUT:
  638.         case RCDO:
  639.             _zperr_ ("Got %s", frametypes[c + FTOFFSET]);
  640.  
  641.             /* **** FALL THRU TO **** */
  642.  
  643.         default:
  644.             if (c >= -3 && c <= FRTYPES)
  645.                 _vfile ("_zgethdr: %s %lx", frametypes[c + FTOFFSET], _Rxpos);
  646.             else
  647.                 _vfile ("_zgethdr: %d %lx", c, _Rxpos);
  648.  
  649.         }    /* switch (c) */
  650.         
  651.     return c;
  652.     }    /* int _zgethdr (char *hdr, int eflag) */
  653.  
  654.  
  655. /****************************************************************************
  656. *    zrbhdr                                                                    *
  657. *    Receive a binary style header (type and position).                        *
  658. ****************************************************************************/
  659.  
  660. static int zrbhdr (char *hdr)
  661.     {
  662.     int c, n;
  663.     unsigned short crc;
  664.  
  665.     if ((c = zdlread ()) & ~0377)
  666.         return c;
  667.  
  668.     Rxtype = c;
  669.     crc = updcrc (c, 0);
  670.  
  671.     for (n = 4; --n >= 0; ++hdr)
  672.         {
  673.         if ((c = zdlread ()) & ~0377)
  674.             return c;
  675.  
  676.         crc = updcrc (c, crc);
  677.         *hdr = (char) c;
  678.         }
  679.  
  680.     if ((c = zdlread ()) & ~0377)
  681.         return c;
  682.  
  683.     crc = updcrc (c, crc);
  684.     if ((c = zdlread ()) & ~0377)
  685.         return c;
  686.  
  687.     crc = updcrc (c, crc);
  688.     if (crc & 0xFFFF)
  689.         {
  690.         _zperr_ ("Bad Header CRC");
  691.         return ERROR;
  692.         }
  693.  
  694.     _Zmodem = 1;
  695.     return Rxtype;
  696.     }    /* static int zrbhdr (char *hdr) */
  697.     
  698.  
  699. /****************************************************************************
  700. *    zrbhdr32                                                                *
  701. *    Receive a binary style header (type and position) with 32 bit FCS.        *
  702. ****************************************************************************/
  703.  
  704. static int zrbhdr32 (char *hdr)
  705.     {
  706.     int c, n;
  707.     UNSL long crc;
  708.  
  709.     if ((c = zdlread ()) & ~0377)
  710.         return c;
  711.  
  712.     Rxtype = c;
  713.     crc = 0xFFFFFFFFL;
  714.     crc = UPDC32 (c, crc);
  715. #ifdef DEBUGZ
  716.     _vfile ("zrbhdr32 c=%X  crc=%lX", c, crc);
  717. #endif
  718.  
  719.     for (n = 4; --n >= 0; ++hdr)
  720.         {
  721.         if ((c = zdlread ()) & ~0377)
  722.             return c;
  723.  
  724.         crc = UPDC32 (c, crc);
  725.         *hdr = (char) c;
  726. #ifdef DEBUGZ
  727.         _vfile ("zrbhdr32 c=%X  crc=%lX", c, crc);
  728. #endif
  729.         }
  730.  
  731.     for (n = 4; --n >= 0;)
  732.         {
  733.         if ((c = zdlread ()) & ~0377)
  734.             return c;
  735.  
  736.         crc = UPDC32 (c, crc);
  737. #ifdef DEBUGZ
  738.         _vfile ("zrbhdr32 c=%X  crc=%lX", c, crc);
  739. #endif
  740.         }
  741.  
  742.     if (crc != 0xDEBB20E3L)
  743.         {
  744.         _zperr_ ("Bad Header CRC"); return ERROR;
  745.         }
  746.  
  747.     _Zmodem = 1;
  748.     return Rxtype;
  749.     }    /* static int zrbhdr32 (char *hdr) */
  750.     
  751.  
  752. /****************************************************************************
  753. *    zrhhdr                                                                    *
  754. *    Receive a hex style header (type and position).                            *
  755. ****************************************************************************/
  756.  
  757. static int zrhhdr (char *hdr)
  758.     {
  759.     int c;
  760.     unsigned short crc;
  761.     int n;
  762.  
  763.     if ((c = zgethex ()) < 0)
  764.         return c;
  765.  
  766.     Rxtype = c;
  767.     crc = updcrc (c, 0);
  768.  
  769.     for (n = 4; --n >= 0; ++hdr)
  770.         {
  771.         if ((c = zgethex ()) < 0)
  772.             return c;
  773.             
  774.         crc = updcrc (c, crc);
  775.         *hdr = (char) c;
  776.         }
  777.  
  778.     if ((c = zgethex ()) < 0)
  779.         return c;
  780.  
  781.     crc = updcrc (c, crc);
  782.     if ((c = zgethex ()) < 0)
  783.         return c;
  784.  
  785.     crc = updcrc (c, crc);
  786.     if (crc & 0xFFFF)
  787.         {
  788.         _zperr_ ("Bad Header CRC");
  789.         return ERROR;
  790.         }
  791.  
  792.     if (_readline (1) == '\r')            /* Throw away possible cr/lf         */
  793.         _readline (1);
  794.         
  795.     _Zmodem = 1;
  796.     return Rxtype;
  797.     }    /* static int zrhhdr (char *hdr) */
  798.     
  799.  
  800. /****************************************************************************
  801. *    zputhex                                                                    *
  802. *    Send a byte as two hex digits.                                            *
  803. ****************************************************************************/
  804.  
  805. static void zputhex (int c)
  806.     {
  807.     static char    digits[] = "0123456789abcdef";
  808.  
  809.     if (_Verbose > 8)
  810.         _vfile ("zputhex: %02X", c);
  811.         
  812.     _sendline (digits[(c & 0xF0) >> 4]);
  813.     _sendline (digits[(c) & 0xF]);
  814.     }    /* static void zputhex (int c) */
  815.     
  816.  
  817. /****************************************************************************
  818. *    zsendline                                                                *
  819. *    Send character <c> with ZMODEM escape sequence encoding.  Escape XON,    *
  820. *    XOFF.  Escape CR following @ (Telenet net escape).                        *
  821. ****************************************************************************/
  822.  
  823. static void zsendline (int c)
  824.     {
  825.     static int lastsent;
  826.  
  827.     switch (c &= 0377)
  828.         {
  829.         case ZDLE:
  830.             _xsendline (ZDLE);
  831.             _xsendline (lastsent = (c ^= 0100));
  832.             break;
  833.  
  834.         case 015:
  835.         case 0215:
  836.             if (!_Zctlesc && (lastsent & 0177) != '@')
  837.                 goto sendit;
  838.  
  839.             /* **** FALL THRU TO **** */
  840.  
  841.         case 020:
  842.         case 021:
  843.         case 023:
  844.         case 0220:
  845.         case 0221:
  846.         case 0223:
  847.             _xsendline (ZDLE);
  848.             c ^= 0100;
  849.  
  850. sendit:
  851.             _xsendline (lastsent = c);
  852.             break;
  853.  
  854.         default:
  855.             if (_Zctlesc && ! (c & 0140))
  856.                 {
  857.                 _xsendline (ZDLE);
  858.                 c ^= 0100;
  859.                 }
  860.  
  861.             _xsendline (lastsent = c);
  862.         }    /* switch (c &= 0377) */
  863.         
  864.     }    /* static void zsendline (int c) */
  865.     
  866.  
  867. /****************************************************************************
  868. *    zgethex, zgeth1                                                            *
  869. *    Decode two lower case hex digits into an 8 bit byte value.                *
  870. ****************************************************************************/
  871.  
  872. static int zgethex (void)
  873.     {
  874.     int c;
  875.  
  876.     c = zgeth1 ();
  877.     if (_Verbose > 8)
  878.         _vfile ("zgethex: %02X", c);
  879.  
  880.     return c;
  881.     }    /* static int zgethex (void) */
  882.     
  883. static int zgeth1 (void)
  884.     {
  885.     int c, n;
  886.  
  887.     if ((c = noxrd7 ()) < 0)
  888.         return c;
  889.  
  890.     n = c - '0';
  891.     if (n > 9)
  892.         n -= ('a' - ':');
  893.  
  894.     if (n & ~0xF)
  895.         return ERROR;
  896.  
  897.     if ((c = noxrd7 ()) < 0)
  898.         return c;
  899.  
  900.     c -= '0';
  901.     if (c > 9)
  902.         c -= ('a' - ':');
  903.  
  904.     if (c & ~0xF)
  905.         return ERROR;
  906.  
  907.     c += (n << 4);
  908.     return c;
  909.     }    /* static int zgeth1 (void) */
  910.     
  911.  
  912. /****************************************************************************
  913. *    zdlread                                                                    *
  914. *    Read a byte, checking for ZMODEM escape encoding including CAN * 5        *
  915. *    which represents a quick abort.                                            *
  916. ****************************************************************************/
  917.  
  918. static int zdlread (void)
  919.     {
  920.     int c;
  921.  
  922. again:
  923.     switch (c = _readline (_Rxtimeout))
  924.         {
  925.         case ZDLE:
  926.             break;
  927.  
  928.         case 023:
  929.         case 0223:
  930.         case 021:
  931.         case 0221:
  932.             goto again;
  933.  
  934.         default:
  935.             if (_Zctlesc && !(c & 0140))
  936.                 {
  937.                 goto again;
  938.                 }
  939.  
  940.             return c;
  941.         }    /* switch (c = _readline (_Rxtimeout)) */
  942.         
  943. again2:
  944.     if ((c = _readline (_Rxtimeout)) < 0)
  945.         return c;
  946.  
  947.     if (c == CAN && (c = _readline (_Rxtimeout)) < 0)
  948.         return c;
  949.  
  950.     if (c == CAN && (c = _readline (_Rxtimeout)) < 0)
  951.         return c;
  952.  
  953.     if (c == CAN && (c = _readline (_Rxtimeout)) < 0)
  954.         return c;
  955.  
  956.     switch (c)
  957.         {
  958.         case CAN:
  959.             return GOTCAN;
  960.  
  961.         case ZCRCE:
  962.         case ZCRCG:
  963.         case ZCRCQ:
  964.         case ZCRCW:
  965.             return (c | GOTOR);
  966.  
  967.         case ZRUB0:
  968.             return 0177;
  969.  
  970.         case ZRUB1:
  971.             return 0377;
  972.  
  973.         case 023:
  974.         case 0223:
  975.         case 021:
  976.         case 0221:
  977.             goto again2;
  978.  
  979.         default:
  980.             if (_Zctlesc && ! (c & 0140))
  981.                 {
  982.                 goto again2;
  983.                 }
  984.  
  985.             if ((c & 0140) ==  0100)
  986.                 return (c ^ 0100);
  987.  
  988.             break;
  989.         }    /* switch (c) */
  990.         
  991.     _zperr_ ("Bad escape sequence %x", c);
  992.     return ERROR;
  993.     }    /* static int zdlread (void) */
  994.  
  995.     
  996. /****************************************************************************
  997. *    noxrd7                                                                    *
  998. *    Read a character from the modem line with timeout.  Eat parity, XON     *
  999. *    and XOFF characters.                                                    *
  1000. ****************************************************************************/
  1001.  
  1002. static int noxrd7 (void)
  1003.     {
  1004.     int c;
  1005.  
  1006.     for (;;)
  1007.         {
  1008.         if ((c = _readline (_Rxtimeout)) < 0)
  1009.             return c;
  1010.  
  1011.         switch (c &= 0177)
  1012.             {
  1013.             case XON:
  1014.             case XOFF:
  1015.                 continue;
  1016.  
  1017.             default:
  1018.                 if (_Zctlesc && !(c & 0140))
  1019.                     continue;
  1020.  
  1021.             case '\r':
  1022.             case '\n':
  1023.             case ZDLE:
  1024.                 return c;
  1025.             }    /* switch (c &= 0177) */
  1026.             
  1027.         }    /* for (;;) */
  1028.         
  1029.     }    /* static int noxrd7 (void) */
  1030.     
  1031.  
  1032. /****************************************************************************
  1033. *    _stohdr                                                                    *
  1034. *    Store long integer pos in _Txhdr.                                        *
  1035. ****************************************************************************/
  1036.  
  1037. void _stohdr (long pos)
  1038.     {
  1039.     _Txhdr[ZP0] = (char) pos;
  1040.     _Txhdr[ZP1] = (char) (pos >> 8);
  1041.     _Txhdr[ZP2] = (char) (pos >> 16);
  1042.     _Txhdr[ZP3] = (char) (pos >> 24);
  1043.     }    /* void _stohdr (long pos) */
  1044.     
  1045.  
  1046. /****************************************************************************
  1047. *    _rclhdr                                                                    *
  1048. *    Recover a long integer from a header.                                    *
  1049. ****************************************************************************/
  1050.  
  1051. long _rclhdr (char *hdr)
  1052.     {
  1053.     long l;
  1054.  
  1055.     l = (hdr[ZP3] & 0377);
  1056.     l = (l << 8) | (hdr[ZP2] & 0377);
  1057.     l = (l << 8) | (hdr[ZP1] & 0377);
  1058.     l = (l << 8) | (hdr[ZP0] & 0377);
  1059.     return l;
  1060.     }    /* long _rclhdr (char *hdr) */
  1061.  
  1062. /* End of zm.c */
  1063.